package com.wpam.scrabble.mobile.communication;

import java.io.IOException;
import java.util.ArrayList;

import com.wpam.scrabble.mobile.GameLogic;
import com.wpam.scrabble.mobile.activities.ServerSearchActivity;
import com.wpam.scrabble.mobile.activities.WaitingForAcceptActivity;
import com.wpam.scrabble.mobile.activities.ServerSearchActivity.ServerAdapter;
import com.wpam.scrabble.mobile.communication.bt.BluetoothManager;
import com.wpam.scrabble.mobile.communication.bt.DeviceNetworkInfo;
import com.wpam.scrabble.mobile.messages.InfoMessage;
import com.wpam.scrabble.mobile.messages.Message;
import com.wpam.scrabble.mobile.messages.MsgSerializer;
import com.wpam.scrabble.mobile.messages.NewTurnMessage;
import com.wpam.scrabble.mobile.messages.StartMessage;

import android.app.Activity;
import android.bluetooth.BluetoothDevice;
import android.preference.PreferenceManager;
import android.widget.TextView;

public class CommunicationManager {
	private final static CommunicationManager instance_ = new CommunicationManager();
	private Activity currentActivity_;
	
	private Thread msgParser_;
	private final MsgBuffer messageBuffer_;
	private InterfaceManager connManager_;
	
	private CommunicationManager() {
		
		currentActivity_ = null;
		messageBuffer_ = new MsgBuffer();
		msgParser_ = null;
		this.connManager_ = BluetoothManager.getInstance();
	}
	
	public static CommunicationManager getInstance(Activity current) {
		
		instance_.currentActivity_ = current;
		instance_.connManager_ = BluetoothManager.getInstance(instance_.currentActivity_);
		return instance_;
	}
	
	public static CommunicationManager getInstance() {
		return instance_;
	}
	
	public Activity getCurrentActivity() {
		return currentActivity_;
	}
	
	public void startReconnectTask() {
		connManager_.startReconnectTask();
	}
	
	public void stopAcceptorTask() {
		connManager_.stopAcceptorTask();
	}

	public void stopReconnectTask() {
		connManager_.stopReconnectTask();
	}
	
	public void stopNetworkActions() {

		connManager_.stopCurrentActions();
		if (msgParser_ != null) {
			msgParser_.interrupt();
			msgParser_ = null;
		}
	}
	
	public MsgBuffer getMessageBuffer() {
		return messageBuffer_;
	}

	public void startServerMsgParser() {

		if (msgParser_ == null || !msgParser_.isAlive()) {
			msgParser_ = new ServerMessageParserThread(messageBuffer_);
			msgParser_.start();
		}
	}

	public void startClientMsgParser() {

		if (msgParser_ == null || !msgParser_.isAlive()) {
			msgParser_ = new ClientMessageParserThread(messageBuffer_);
			msgParser_.start();
		}
	}
	
	void sendServerInfo(BluetoothDevice receiver) throws Exception {
		writeAsServer(receiver, MsgSerializer.serialize(new InfoMessage(PreferenceManager.getDefaultSharedPreferences(currentActivity_).getAll())));
	}
	
	void sendDumpInfo(BluetoothDevice receiver) throws Exception {
		writeAsServer(receiver, MsgSerializer.serialize(new InfoMessage(PreferenceManager.getDefaultSharedPreferences(currentActivity_).getAll(), GameLogic.getInstance().getGameBoard(), GameLogic.getInstance().getScoreBoard(), GameLogic.getInstance().getPlayerManager().getNameOfSender(receiver))));
	}
	
	public void sendMoveAndNextTurnMsgToEverybody(Message message) {
		
		forwardMessage(message);
		
		boolean gameEnded = GameLogic.getInstance().isGameEnded();
		if (!gameEnded)
			GameLogic.getInstance().nextTurn();
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		forwardMessage(new NewTurnMessage(GameLogic.getInstance().getScoreBoard(), gameEnded));
	}
	
	/*
	 * Sends message to all players but not to the sender of the message (if specified)
	 */
	public void forwardMessage(Message message) {
		connManager_.forwardMessage(message);
	}

	public static void writeAsServer(DeviceNetworkInfo receiver, byte[] buffer) {
		instance_.connManager_.writeAsServer(receiver, buffer);
	}

	public static void writeAsServer(BluetoothDevice receiver, byte[] buffer) throws Exception {
		instance_.connManager_.writeAsServer(receiver, buffer);
	}
	
	public void writeAsClient(byte[] buffer) throws IOException {
		instance_.connManager_.writeAsClient(buffer);
	}

	public static void disconnectClient() {
		instance_.connManager_.disconnectClient();
	}
	
	public static void disconnectAllClients() {
		instance_.connManager_.disconnectAllClients();
	}

	public static String getMyName() {
		return instance_.connManager_.getMyName();
	}
	
	public void startGame(StartMessage startMessage) {
		
		if (currentActivity_ instanceof WaitingForAcceptActivity)
			((WaitingForAcceptActivity)currentActivity_).startGame(startMessage);
	}

	public void sendStartMessageToEverybody(ArrayList<String> playerNames) {

		for (DeviceNetworkInfo device : connManager_.getConnectedPlayers())
			writeAsServer(device, MsgSerializer.serialize(new StartMessage(playerNames, GameLogic.getInstance().getLettersOfPlayer(GameLogic.getInstance().getPlayerManager().getNameOfSender(device)))));
	}

	public void startDisconnectListener() {
		connManager_.startDisconnectListener();
	}

	public void resumeDisconnectListener() {
		connManager_.resumeDisconnectListener();
	}
	
	public void stopDisconnectListener() {
		connManager_.stopDisconnectListener();
	}

	public void startDiscoveryListener(ServerSearchActivity parent, ServerAdapter adapter, TextView status) {
		connManager_.startDiscoveryListener(parent, adapter, status);
	}
	
	public void resumeDiscoveryListener() {
		connManager_.resumeDiscoveryListener();
	}

	public void stopDiscoveryListener() {
		connManager_.stopDiscoveryListener();
	}
	
	public void disconnectSelfGently() {
		
		try {
			connManager_.disconnectSelfGently();
		}
		catch (IOException e) {
			// TODO: Auto generated
			e.printStackTrace();
		}
		stopNetworkActions();
	}

	public boolean isPlayerConnected(String name) {
		return connManager_.isPlayerConnected(name);
	}

	public void disconnectSingleClient(BluetoothDevice senderDevice) {
		connManager_.disconnectSingleClient(senderDevice);
	}
}
